﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace MegauploadForum
{
    public class LinksParserWorker : IDisposable
    {
        #region Members

        private bool m_initialized;
        private IList<string> m_parsedLinks;
        private AutoResetEvent m_webBrowserSynchroziedEvent;
        private Thread m_thread;
        private int m_id;
        private static int s_id;

        #endregion

        #region Properties

        public bool Working { get; private set; }
        public TimeSpan WaitBetweenTwoLinks { get; set; }
        public WebBrowser WebBrowser { get; set; }
        public BlockingCollection<ParsingRequest> Queue { private get; set; }

        #endregion

        #region Events

        public event EventHandler<ParsingResultEventArgs> OnParsed;

        #endregion

        #region Public Methods
        
        public void Init()
        {
            m_id = Interlocked.Increment(ref s_id);
            m_thread = new Thread(InnerStart);
            m_webBrowserSynchroziedEvent = new AutoResetEvent(false);
            m_parsedLinks = new List<string>();

            WebBrowser.DocumentCompleted += m_webBrowser_DocumentCompleted;

            m_initialized = true;
        }

        public void Start()
        {
            if (!m_initialized)
            {
                throw new NotSupportedException("Can't start worker before initialized");
            }

            Console.WriteLine("LinksParserWorker({0}) Start", m_id);
            m_thread.Start();
        }

        public void Dispose()
        {
            Console.WriteLine("LinksParserWorker({0}) Dispose", m_id);
            m_thread.Abort();
        }

        #endregion

        #region Private Methods

        private void InnerStart()
        {
            while (true)
            {
                Console.WriteLine("LinksParserWorker({0}) Before Take", m_id);
                ParsingRequest request = Queue.Take();
                Console.WriteLine("LinksParserWorker({0}) After Take", m_id);
                Parse(request);
            }
        }

        private void m_webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            m_webBrowserSynchroziedEvent.Set();
        }

        private void Parse(ParsingRequest request)
        {
            if (!m_initialized)
            {
                throw new NotSupportedException("Can't parse before initialized");
            }
            if (Working)
            {
                throw new NotSupportedException("Can't parse new request before end the current request.");
            }

            Working = true;
            m_parsedLinks.Clear();
            m_webBrowserSynchroziedEvent.Reset();

            foreach (string link in request.Links)
            {
                Console.WriteLine("Try process({1}) {0}", link, m_id);
                WebBrowser.Invoke(new MethodInvoker(() => WebBrowser.Navigate(link)));
                Console.WriteLine("Wait for site will load({0})", m_id);
                m_webBrowserSynchroziedEvent.WaitOne();
                string parsedLink = WebBrowser.Url.ToString();
                Console.WriteLine("Found({1}) {0}", parsedLink, m_id);
                m_parsedLinks.Add(parsedLink);
                Console.WriteLine("Wait({1}) {0} seconds", WaitBetweenTwoLinks.TotalSeconds, m_id);
                Thread.Sleep(WaitBetweenTwoLinks);
            }

            if (OnParsed != null)
            {
                ParsingResultEventArgs args = new ParsingResultEventArgs();
                args.Result = new ParsingResult
                {
                    Links = new List<string>(m_parsedLinks)
                };
                OnParsed(this, args);
            }

            Working = false;
        }

        #endregion        
    }

    
}
